﻿using System;
using System.Linq;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Collections;
using System.Windows.Controls;
using System.Windows;
using System.Windows.Markup;

namespace EnsureWeb.UI.Controls
{
    public class CheckboxList : ContentControl
    {
        public static readonly DependencyProperty ItemsSourceProperty =
            DependencyProperty.Register("ItemsSource", typeof(IEnumerable), typeof(CheckboxList),
                                        new PropertyMetadata(null, ItemsSourceChanged));

        public static readonly DependencyProperty SelectedItemsProperty =
            DependencyProperty.Register("SelectedItems", typeof(IEnumerable), typeof(CheckboxList),
                                        new PropertyMetadata(null));

        public static readonly DependencyProperty DisplayMemberPathProperty =
            DependencyProperty.Register("DisplayMemberPath", typeof(string), typeof(CheckboxList),
                                        new PropertyMetadata(string.Empty));

        private static ObservableCollection<InternalModel> _internalCollection;
        private static ItemsControl itemsControl = new ItemsControl();

        public CheckboxList()
        {
            Content = itemsControl;
            SelectedItems = new ObservableCollection<object>();
        }

        public string DisplayMemberPath
        {
            get { return GetValue(DisplayMemberPathProperty) as string; }
            set
            {
                SetValue(DisplayMemberPathProperty, value);

                if (value != null)
                    itemsControl.ItemTemplate =
                        (DataTemplate)XamlReader.Load(
                            @"<DataTemplate xmlns=""http://schemas.microsoft.com/client/2007"">
                                  <CheckBox Content=""{Binding Value." + DisplayMemberPath + @", Mode=TwoWay}"" 
                                            IsChecked=""{Binding Selected, Mode=TwoWay}""/>
                              </DataTemplate>");
            }
        }

        public IEnumerable ItemsSource
        {
            get { return GetValue(ItemsSourceProperty) as ObservableCollection<object>; }
            set { SetValue(ItemsSourceProperty, value); }
        }

        public ObservableCollection<object> SelectedItems
        {
            get
            {
                return GetValue(SelectedItemsProperty) as ObservableCollection<object>;
            }
            set
            {
                SetValue(SelectedItemsProperty, value);
            }
        }

        private static void ItemsSourceChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {

            ((CheckboxList)d).BuildInternalCollection(e.NewValue as IEnumerable);

        }

        private void BuildInternalCollection(IEnumerable collection)
        {
            _internalCollection = new ObservableCollection<InternalModel>();
            foreach (var o in collection)
            {
                var nContainerItem = new InternalModel { Selected = false, Value = o };
                nContainerItem.PropertyChanged += nContainerItem_PropertyChanged;
                _internalCollection.Add(nContainerItem);
            }

            itemsControl.ItemsSource = _internalCollection;

        }

        void nContainerItem_PropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            if (SelectedItems == null)
                SelectedItems = new ObservableCollection<object>();

            SelectedItems.Clear();

            foreach (var o in _internalCollection.Where(internalModel => internalModel.Selected))
                SelectedItems.Add(o.Value);
        }

        #region Nested type: InternalModel

        public class InternalModel : GalaSoft.MvvmLight.ViewModelBase
        {
            public object Value { get; set; }
            private bool _selected;
            public bool Selected
            {
                get { return _selected; }
                set
                {
                    _selected = value;
                    RaisePropertyChanged("Selected");
                }
            }
        }

        #endregion
    }
}
